﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Objects;
using System.ComponentModel;
using Relocation.Data;

namespace Relocation.Service
{
	/// <summary>
	/// 数据库访问类。
	/// </summary>
	public class DataModel : RelocationServerEntities
	{
		public event EventHandler OnSaveChanges;

		/// <summary>
		/// 保存数据库所有表关键字字段的当前最大值
		/// </summary>
		private static Dictionary<Type, int> _primaryKeysCache = new Dictionary<Type, int>();

		public static Dictionary<Type, int> primaryKeysCache
		{
			get
			{
				return _primaryKeysCache;
			}
		}

		#region 泛型相关方法

		/// <summary>
		/// 新生成一个数据表ID.
		/// </summary>
		/// <typeparam name="TEntity">实体对象类型.</typeparam>
		/// <param name="table">The table.</param>
		/// <param name="idSelector">The id selector.</param>
		/// <returns>返回一个新ID</returns>
		public static int GenerateID<TEntity>(
			Func<DataModel, ObjectQuery<TEntity>> table,
			Func<TEntity, int> idSelector) where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			lock (_primaryKeysCache)
			{

				int primaryKey = 0;
				if (!_primaryKeysCache.TryGetValue(typeof(TEntity), out primaryKey))
				{
					using (DataModel model = new DataModel())
					{
						primaryKey = table(model).Any() ? table(model).Max(idSelector) : 0;
					}
				}
				primaryKey++;
				_primaryKeysCache[typeof(TEntity)] = primaryKey;
				return primaryKey;
			}
		}

		/// <summary>
		/// Generates the ID.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <returns>返回一个新ID</returns>
		public static int GenerateID<TEntity>(TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			lock (_primaryKeysCache)
			{
				int primaryKey = 0;
				if (!_primaryKeysCache.TryGetValue(typeof(TEntity), out primaryKey))
				{
					primaryKey = 0;
				}
				primaryKey++;
				_primaryKeysCache[typeof(TEntity)] = primaryKey;
				return primaryKey;
			}
		}

		/// <summary>
		/// Gets the search string.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <returns>返回生成的查询串</returns>
		private string getSearchString<TEntity>(TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = "";
			//string keyName = entity.EntityKey.EntityKeyValues[0].Key;
			Type entityType = entity.GetType();
			foreach (var fieldType in entityType.GetProperties())
			{
				if (!fieldType.CanWrite)
					continue;
				if (fieldType.Name == "EntityState" || fieldType.Name == "EntityKey")
					continue;
				var fieldValue = fieldType.GetValue(entity, null);
				if (fieldType.PropertyType.IsValueType)
				{
					if (fieldValue != null)
					{
						if (fieldType.PropertyType.Name.StartsWith("Int"))//fieldType.Name == keyName && 
						{
							if ((int)fieldValue != 0)
							{
								if (condition != "")
									condition += " and ";
								condition += "it." + fieldType.Name + "=" + fieldValue.ToString() + "";
							}
						} else if (fieldType.PropertyType.FullName.Contains("System.Int") || fieldType.PropertyType.FullName.Contains("System.Decimal"))
						{
							if (condition != "")
								condition += " and ";
							condition += "it." + fieldType.Name + "=" + fieldValue.ToString() + "";
						} else if (fieldType.PropertyType.FullName.Contains("System.DateTime"))
						{
							if (condition != "")
								condition += " and ";
							System.DateTime value = (System.DateTime)fieldValue;
							condition += "Year(it." + fieldType.Name + ")=" + value.Year + " and Month(it." + fieldType.Name + ")=" + value.Month + " and Day(it." + fieldType.Name + ")=" + value.Day;
						} else if (fieldType.PropertyType.FullName.Contains("Boolean"))
						{
							if (condition != "")
								condition += " and ";
							Boolean value = (Boolean)fieldValue;
							condition += "it." + fieldType.Name + "=" + value.ToString();
						} else
						{
							//Console.WriteLine("“" + fieldType.PropertyType.FullName + "”数据库类型未找到");
							//throw new Exception("“" + fieldType.PropertyType.FullName + "”数据库类型未找到");
						}
					}
				} else if (fieldType.PropertyType.Name == "String")
				{
					if (fieldValue != null)
					{
						if (fieldValue.ToString() != "")
						{
							if (condition != "")
								condition += " and ";
							condition += "it." + fieldType.Name + " like '%" + fieldValue.ToString().Replace("'", "''") + "%'";
						}
					}
				}
			}
			return condition;
		}

		/// <summary>
		/// Searches the specified entity.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <returns>返回查询结果</returns>
		public ObjectQuery<TEntity> search<TEntity>(TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = getSearchString(entity);
			//System.Windows.Forms.MessageBox.Show(condition);
			Type thisType = this.GetType();
			ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
			if (condition != "")
				query = query.Where(condition);
			return query;
		}



		/// <summary>
		/// Searches the specified query.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="query">The query.</param>
		/// <param name="entity">The entity.</param>
		/// <returns>返回生成的查询串</returns>
		public ObjectQuery<TEntity> search<TEntity>(ObjectQuery<TEntity> query, TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = getSearchString(entity);
			if (condition != "")
				query = query.Where(condition);
			Console.WriteLine(query.ToTraceString());
			return query;
		}

		/// <summary>
		/// Searches the specified entity.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <param name="orderField">The order field.</param>
		/// <returns>返回生成的查询串</returns>
		public ObjectQuery<TEntity> search<TEntity>(TEntity entity, string orderField)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = getSearchString(entity);
			Type thisType = this.GetType();
			ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
			if (condition != "")
				query = query.Where(condition);
			if (orderField != "")
				query = query.OrderBy("it." + orderField);
			Console.WriteLine(query.ToTraceString());
			return query;
		}

		/// <summary>
		/// Searches the specified query.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="query">The query.</param>
		/// <param name="entity">The entity.</param>
		/// <param name="orderField">The order field.</param>
		/// <returns>返回生成的查询串</returns>
		public ObjectQuery<TEntity> search<TEntity>(ObjectQuery<TEntity> query, TEntity entity, string orderField)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = getSearchString(entity);
			if (condition != "")
				query = query.Where(condition);
			if (orderField != "")
				query = query.OrderBy("it." + orderField);
			Console.WriteLine(query.ToTraceString());
			return query;
		}

		/// <summary>
		/// Searches the specified entity.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <param name="orderField">The order field.</param>
		/// <param name="direction">The direction.</param>
		/// <returns>返回生成的查询串</returns>
		public ObjectQuery<TEntity> search<TEntity>(TEntity entity, string orderField, ListSortDirection direction)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = getSearchString(entity);
			Type thisType = this.GetType();
			ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
			if (condition != "")
				query = query.Where(condition);
			if (orderField != "")
				if (direction == ListSortDirection.Ascending)
				{
					query = query.OrderBy("it." + orderField);
				} else
				{
					query = query.OrderBy("it." + orderField + " desc");
				}
			Console.WriteLine(query.ToTraceString());
			return query;
		}

		/// <summary>
		/// Searches the specified query.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="query">The query.</param>
		/// <param name="entity">The entity.</param>
		/// <param name="orderField">The order field.</param>
		/// <param name="direction">The direction.</param>
		/// <returns>返回生成的查询串</returns>
		public ObjectQuery<TEntity> search<TEntity>(ObjectQuery<TEntity> query, TEntity entity, string orderField, ListSortDirection direction)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			string condition = getSearchString(entity);
			if (condition != "")
				query = query.Where(condition);
			if (orderField != "")
				if (direction == ListSortDirection.Ascending)
				{
					query = query.OrderBy("it." + orderField);
				} else
				{
					query = query.OrderBy("it." + orderField + " desc");
				}
			Console.WriteLine(query.ToTraceString());
			return query;
		}

		/// <summary>
		/// Searches the specified entity.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <param name="fromDate">From date.</param>
		/// <param name="toDate">To date.</param>
		/// <returns>返回生成的查询串</returns>
		public ObjectQuery<TEntity> search<TEntity>(TEntity entity, String fromDate, String toDate)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			System.DateTime dateTime;
			string condition = getSearchString(entity);
			if (!String.IsNullOrEmpty(fromDate))
			{
				if (System.DateTime.TryParse(fromDate, out dateTime))
				{
					if (condition != "")
						condition += " and ";
					condition += "it.created>=datetime'" + dateTime.Date + "'";
				}
			}
			if (!String.IsNullOrEmpty(toDate))
			{
				if (System.DateTime.TryParse(toDate, out dateTime))
				{
					if (condition != "")
						condition += " and ";
					condition += "it.created<=datetime'" + dateTime.Date + "'";
				}
			}
			Type thisType = this.GetType();
			ObjectQuery<TEntity> query = (ObjectQuery<TEntity>)(thisType.GetProperty(entity.GetType().Name).GetValue(new DataModel(), null));
			if (condition != "")
				query = query.Where(condition);
			Console.WriteLine(query.ToTraceString());
			return query;
		}

		/// <summary>
		/// Inserts the or update object.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="entity">The entity.</param>
		/// <returns>插入或更新记录数</returns>
		public int Save<TEntity>(TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			try
			{
				Type entityType = entity.GetType();
				if (entity.EntityState == System.Data.EntityState.Unchanged)
					return 0;
				if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
				{
					//entityType.GetProperty(entity.EntityKey.EntityKeyValues[0].Key).SetValue(entity, GenerateID(entity), null);
					string entityName = entity.ToString();
					entityName = entityName.Substring(entityName.LastIndexOf('.') + 1);
					entityName = this.GetType().GetProperty(entityName) != null ? entityName : entityName + "s";
					this.AddObject(entityName, entity);

				}
				if (OnSaveChanges != null)
					OnSaveChanges(null, null);

				return this.SaveChanges();
			} catch (Exception ex)
			{
				if (entity != null && entity.EntityKey != null)
				{
					if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
					{
						this.Detach(entity);
					} else
					{
						this.Refresh(RefreshMode.StoreWins, entity);
					}
				}

				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 删除记录
		/// </summary>
		/// <param name="entity">所要删除的对象</param>
		/// <returns>删除的记录数</returns>
		/// 
		/// <typeparam name="TEntity"></typeparam><remarks></remarks>
		public int Delete<TEntity>(TEntity entity)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			try
			{
				if (entity.EntityKey == null)
					throw new Exception("entity对象尚未附加");
				DeleteObject(entity);
				if (OnSaveChanges != null)
					OnSaveChanges(null, null);
				return this.SaveChanges();
			} catch (Exception ex)
			{
				if (entity != null && entity.EntityKey != null)
					this.Refresh(RefreshMode.StoreWins, entity);
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// Sorts the specified query.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="query">The query.</param>
		/// <param name="sortField">The sort field.</param>
		/// <returns>排序结果</returns>
		public ObjectQuery<TEntity> sort<TEntity>(ObjectQuery<TEntity> query, string sortField)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			try
			{
				ObjectQuery<TEntity> queryReturn = query.OrderBy("it." + sortField);
				//Console.WriteLine(queryReturn.ToTraceString());
				return queryReturn;
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// Sorts the specified query.
		/// </summary>
		/// <typeparam name="TEntity">The type of the entity.</typeparam>
		/// <param name="query">The query.</param>
		/// <param name="sortField">The sort field.</param>
		/// <param name="direction">The direction.</param>
		/// <returns>排序结果</returns>
		public ObjectQuery<TEntity> sort<TEntity>(ObjectQuery<TEntity> query, string sortField, ListSortDirection direction)
			where TEntity : System.Data.Objects.DataClasses.EntityObject
		{
			try
			{
				if (query == null || String.IsNullOrEmpty(sortField))
					return query;
				string directionStr = (direction == ListSortDirection.Descending) ? " desc" : "";
				ObjectQuery<TEntity> queryReturn = query.OrderBy("it." + sortField + directionStr);
				Console.WriteLine(queryReturn.ToTraceString());
				return queryReturn;
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}



		#endregion

		#region User相关方法
		public User getUserById(int id)
		{
			try
			{
				return this.Users.Where(c => c.user_id == id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}


		public User getUserByName(string name)
		{
			try
			{
				return this.Users.Where("it.name='" + name.Replace("'", "''") + "'").FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		public User getUserByNameAndPassword(string name, string password)
		{
			try
			{
				return this.Users.Where(t => t.name == name && t.password == password && t.enable == 1).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}
		#endregion

		#region Houses相关方法
		/// <summary>
		/// 根据id获得Houses
		/// </summary>
		/// <param name="id">Houses的id</param>
		/// <returns>Houses对象</returns>
		public House getHouseById(int id)
		{
			try
			{
				return this.Houses.Where(c => c.house_id == id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 根据Houses_code获得Houses
		/// </summary>
		/// <param name="h_code">Houses的Houses_Code</param>
		/// <returns>Houses</returns>
		public House GetHouseByCode(string hCode)
		{

			try
			{
				return this.Houses.Where("it.house_code='" + hCode.Replace("'", "''") + "'").FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 根据h_storeroom获得Houses
		/// </summary>
		/// <param name="h_code">Houses的Houses_Code</param>
		/// <returns>Houses</returns>
		public House GetHouseBystoreroom(string h_storeroom)
		{
			try
			{
				return this.Houses.Where("it.storeroom='" + h_storeroom.Replace("'", "''") + "'").FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 查找Houses
		/// </summary>
		/// <param name="h">Houses对象</param>
		/// <returns>结果集</returns>
		public ObjectQuery<House> GetHouses(House h)
		{
			try
			{
				ObjectQuery<House> qu = search(h);
				return qu;
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		public void ChangeIsUsed(House house, bool isUsed)
		{
			house.isUsed = isUsed;
			this.Save(house);
		}

		#endregion

		#region Placement相关方法
		public Placement GetPlacementById(int id)
		{
			try
			{
				return this.Placements.Where(c => c.placement_id == id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 根据relocatees_id查找Placement
		/// </summary>
		/// <param name="relocateesId"></param>
		/// <returns></returns>
		public ObjectQuery<Placement> getPlacementByRelocateesId(int id)
		{
			try
			{
				return this.Placements.Where("it.Relocatee.relocatees_id=" + id.ToString());
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 根据id_number查找Placement
		/// </summary>
		/// <param name="relocateesId"></param>
		/// <returns></returns>
		public Placement getPlacementByIdNumber(string id_number)
		{
			try
			{
				return this.Placements.Where("it.id_number='" + id_number.Replace("'", "''") + "'").FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;

			}
		}
		#endregion

		#region Projects相关方法

		/// <summary>
		/// 根据project_id查找Projects
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public Project getProjectById(int id)
		{
			try
			{
				return this.Projects.Where(c => c.project_id == id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 得到项目的记录个数
		/// </summary>
		/// <returns></returns>
		public int getProjectsCount()
		{
			return this.Projects.Count();
		}

		#endregion

		#region Relocatees相关方法

		public Relocatee getRelocateesById(int id)
		{
			try
			{
				return this.Relocatees.Where(c => c.relocatees_id == id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		public ObjectQuery<Relocatee> getRelocateesByProjectId(int id)
		{
			try
			{
				return this.Relocatees.Where("it.Project.project_id = " + id);
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		



		#endregion

		#region Relocatees_House相关方法

		public Relocatees_House getRelocateesHouseById(int relocatees_id, int house_id)
		{
			try
			{
				return this.Relocatees_House.Where(c => c.Relocatee.relocatees_id == relocatees_id && c.House.house_id == house_id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		/// <summary>
		/// 根据relocatees_id查找Relocatees_House
		/// </summary>
		/// <param name="relocateesId"></param>
		/// <returns></returns>
		public ObjectQuery<Relocatees_House> getRelocateesHouseByRelocateesId(int relocateesId)
		{
			try
			{
				ObjectQuery<Relocatees_House> query = this.Relocatees_House;
				query = query.Where("it.Relocatee.relocatees_id = " + relocateesId);
				return query;
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}

		public Relocatees_House getRelocateesHouseById(int _relocatees_house_id)
		{
			try
			{
				return this.Relocatees_House.Where(c => c.relocatees_house_id == _relocatees_house_id).FirstOrDefault();
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}
		}
		#endregion

		/// <summary>
		/// 返回所有数据库中的Files的文件路径
		/// </summary>
		/// <returns></returns>
		public List<string> GetAllFilesPath()
		{
			return this.Files.Select(t => t.path).ToList();
		}


		/// <summary>
		/// 此方法用于修复安置房的分配状态
		/// </summary>
		public void RepairState()
		{
			List<Relocatee> RelocateesList = this.Relocatees.ToList<Relocatee>();
			IEnumerable<House> HousesList = this.Houses.AsEnumerable<House>();
			List<int> UsedHousesIdList = this.Relocatees_House.Select(t => t.House.house_id).ToList<int>();

			try
			{
				foreach (Relocatee r in RelocateesList)
				{
					//this.UpdateStatus(r);
					throw new Exception("");
				}

				//修复安置房“是否使用字段”
				foreach (House house in HousesList)
				{
					bool isUsed = UsedHousesIdList.Contains(house.house_id);
					if (house.isUsed != isUsed)
					{
						house.isUsed = isUsed;
						this.Save(house);
					}
				}
			} catch (Exception ex)
			{
				Console.WriteLine(ex);
				throw;
			}

		}


	}

	static public class ObjectSetExpend
	{
		//static public void Save<TEntity>(TEntity entity)
		//    where TEntity : System.Data.Objects.DataClasses.EntityObject
		//{
		//    try
		//    {
		//        Type entityType = entity.GetType();
		//        ObjectContext context=entity.
		//        if (entity.EntityState == System.Data.EntityState.Unchanged)
		//            return 0;
		//        if (entity.EntityState == System.Data.EntityState.Detached | entity.EntityState == System.Data.EntityState.Added)
		//        {
		//            //entityType.GetProperty(entity.EntityKey.EntityKeyValues[0].Key).SetValue(entity, GenerateID(entity), null);
		//            string entityName = entity.ToString();
		//            entityName = entityName.Substring(entityName.LastIndexOf('.') + 1);
		//            this.AddObject(entityName + "s", entity);

		//        }
		//        if (OnSaveChanges != null)
		//            OnSaveChanges(null, null);

		//        return this.SaveChanges();
		//    }
		//    catch (Exception ex)
		//    {
		//        if (entity != null && entity.EntityKey != null)
		//            this.Refresh(RefreshMode.StoreWins, entity);
		//        Console.WriteLine(ex);
		//        throw;
		//    }

		//}


	}
}
